#include "common.h"
#include "object.h"

#include "asset.h"
#include "mesh.h"
#include "effect.h"
#include "assetmanager.h"

IMPLEMENT_RTTI( Effect, Asset )

Effect::Effect( const std::string& name )
:	Asset( name )
,	_pEffect( NULL )
{
}

Effect::~Effect()
{
	if( _pEffect )
	{
		_pEffect->Release();
		_pEffect = NULL;
	}
}

Effect* Effect::Create( const std::string& name, const std::string& path )
{
	if( AssetManager::Find( name ) )
	{
		return AssetManager::GetEffect( name );
	}
	
	FILE* fp;
	fopen_s( &fp, path.c_str(), "r" );
	if( fp == NULL )
	{
		assert( false && "File not exists!" );
	}
	fclose( fp );


	Effect* pEffect = new Effect( name );
	if( pEffect == NULL )
	{
		assert( false );
		return NULL;
	}

	LPDIRECT3DDEVICE9 device = Core::GetInstance().GetD3dDevice();
	LPD3DXEFFECT effect = NULL;
	LPD3DXBUFFER pError;
	if( FAILED(
		D3DXCreateEffectFromFileA( 
			device,
			path.c_str(),
			NULL, 
			NULL, 
			0,
			NULL,
			&effect,
			&pError 
	) ) )
	{
		const char* error = ( LPCSTR )pError->GetBufferPointer();
		MessageBoxA( NULL, error, "Error", MB_OK );
		return NULL;
	}

	pEffect->_pEffect = effect;
	AssetManager::Register( name, pEffect );
	return pEffect;
}

D3DXHANDLE Effect::GetConstantHandle( const std::string& name )
{
	ConstantTable::iterator it = _consts.find( name );

	return ( it == _consts.end() )? NULL : _consts[ name ].second;
}

void Effect::SetConstant( const std::string& name, const std::string& type )
{
	D3DXHANDLE handle = _pEffect->GetParameterByName( NULL, name.c_str() );
	if( handle == NULL )
	{
		assert( false );
	}
	_consts[ name ] = std::pair< std::string, D3DXHANDLE >( type, handle );
}

void Effect::SetTechniuqe( const std::string& name )
{
	D3DXHANDLE handle = _pEffect->GetTechniqueByName( name.c_str() );
	_techs[ name ] = handle; 
}

void Effect::SetPass( const std::string& techName, const std::string& passName )
{
	D3DXHANDLE handle = _pEffect->GetPassByName( _techs[ techName ], passName.c_str() );
	_passes[ _techs[ techName ] ].push_back( std::pair< std::string, D3DXHANDLE >(passName, handle ) );
}